#include "ArbreAVL.h"
#include "gtest/gtest.h"

using tp3::ArbreAVL;
using std::exception;
using std::logic_error;
using std::cerr;
using std::cout;
using std::endl;

TEST(ArbreAVL, arbreNouvellementConstruitOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      EXPECT_TRUE(unArbre.estVide());
      EXPECT_EQ(0, unArbre.taille());
      EXPECT_THROW(unArbre.hauteur(), logic_error);

   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterUnNoeudArbreVideOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(3,5);
      EXPECT_FALSE(unArbre.estVide());
      EXPECT_EQ(1, unArbre.taille());
      EXPECT_EQ(0, unArbre.hauteur());
      EXPECT_TRUE(unArbre.appartient(3));
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreVideSansRebalancementOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(2, 2);
      unArbre.inserer(1, 1);
      unArbre.inserer(3, 3);

      EXPECT_EQ(3, unArbre.taille());
      EXPECT_EQ(1, unArbre.hauteur());
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreVideZigZigGaucheOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(3, 3);
      unArbre.inserer(2, 2);
      unArbre.inserer(1, 1);

      EXPECT_EQ(3, unArbre.taille());
      EXPECT_EQ(1, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(1);
      EXPECT_EQ(2, parent);

      parent = unArbre.parent(3);
      EXPECT_EQ(2, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreVideZigZigDroitOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(1, 1);
      unArbre.inserer(2, 2);
      unArbre.inserer(3, 3);

      EXPECT_EQ(3, unArbre.taille());
      EXPECT_EQ(1, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(1);
      EXPECT_EQ(2, parent);
      EXPECT_EQ(2, parent);

      parent = unArbre.parent(3);
      EXPECT_EQ(2, parent);
      EXPECT_EQ(2, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreVideZigZagGaucheOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(3, 3);
      unArbre.inserer(1, 1);
      unArbre.inserer(2, 2);

      EXPECT_EQ(3, unArbre.taille());
      EXPECT_EQ(1, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(1);
      EXPECT_EQ(2, parent);
      EXPECT_EQ(2, parent);

      parent = unArbre.parent(3);
      EXPECT_EQ(2, parent);
      EXPECT_EQ(2, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreVideZigZagDroitOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(1, 1);
      unArbre.inserer(3, 3);
      unArbre.inserer(2, 2);

      EXPECT_EQ(3, unArbre.taille());
      EXPECT_EQ(1, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(1);
      EXPECT_EQ(2, parent);
      EXPECT_EQ(2, parent);

      parent = unArbre.parent(3);
      EXPECT_EQ(2, parent);
      EXPECT_EQ(2, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreHauteur1ZigZigGaucheOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(8,8);
      unArbre.inserer(5,5);
      unArbre.inserer(9,9);

      unArbre.inserer(4,4);
      unArbre.inserer(3,3);

      EXPECT_EQ(5, unArbre.taille());
      EXPECT_EQ(2, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(3);
      EXPECT_EQ(4, parent);

      parent = unArbre.parent(4);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(5);
      EXPECT_EQ(4, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreHauteur1ZigZagGaucheOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(8,8);
      unArbre.inserer(6,6);
      unArbre.inserer(9,9);

      unArbre.inserer(4,4);
      unArbre.inserer(5,5);

      EXPECT_EQ(5, unArbre.taille());
      EXPECT_EQ(2, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(4);
      EXPECT_EQ(5, parent);

      parent = unArbre.parent(5);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(6);
      EXPECT_EQ(5, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreHauteur1ZigZigDroitOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);

      unArbre.inserer(8,8);
      unArbre.inserer(9,9);

      EXPECT_EQ(5, unArbre.taille());
      EXPECT_EQ(2, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(7);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(8);
      EXPECT_EQ(5, parent);

      parent = unArbre.parent(9);
      EXPECT_EQ(8, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ajouterTroisNoeudsArbreHauteur1ZigZagDroitOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);

      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      EXPECT_EQ(5, unArbre.taille());
      EXPECT_EQ(2, unArbre.hauteur());

      int parent;
      parent = unArbre.parent(7);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(8);
      EXPECT_EQ(5, parent);

      parent = unArbre.parent(9);
      EXPECT_EQ(8, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, insererElementIdentiquePasLancePasExceptionOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(5,5);
      unArbre.inserer(5,5);
      unArbre.inserer(5,5);

      EXPECT_EQ(3, unArbre.taille());
      EXPECT_EQ(1, unArbre.hauteur());
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }

}

TEST(ArbreAVL, successeurOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);

      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      int successeur = unArbre.successeur(4);
      EXPECT_EQ(5, successeur);
      successeur = unArbre.successeur(5);
      EXPECT_EQ(7, successeur);
      successeur = unArbre.successeur(7);
      EXPECT_EQ(8, successeur);
      successeur = unArbre.successeur(8);
      EXPECT_EQ(9, successeur);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, successeurExceptions)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      //arbre vide
      EXPECT_THROW(unArbre.successeur(1), logic_error);

      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);

      unArbre.inserer(9,9);
      unArbre.inserer(8,8);
      //elment maximum
      EXPECT_THROW(unArbre.successeur(9), logic_error);
      //element n'appartient pas a l'arbre
      EXPECT_THROW(unArbre.successeur(20), logic_error);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, appartientOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);

      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      EXPECT_TRUE(unArbre.appartient(4));
      EXPECT_TRUE(unArbre.appartient(5));
      EXPECT_TRUE(unArbre.appartient(7));
      EXPECT_TRUE(unArbre.appartient(8));
      EXPECT_TRUE(unArbre.appartient(9));

      EXPECT_FALSE(unArbre.appartient(10));
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, parentExceptionsOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      // arbre vide
      EXPECT_THROW(unArbre.parent(10), logic_error);

      unArbre.inserer(5,5);
      // racine
      EXPECT_THROW(unArbre.parent(5), logic_error);

      unArbre.inserer(4,4);
      unArbre.inserer(7,7);

      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      // element appartenant pas a l'arbre
      EXPECT_THROW(unArbre.parent(10), logic_error);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ConstructeurCopieOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      ArbreAVL<int, int> unAutreArbre(unArbre);
      EXPECT_EQ(unArbre.hauteur(), unAutreArbre.hauteur());
      EXPECT_EQ(unArbre.taille(), unAutreArbre.taille());
      EXPECT_EQ(unArbre.estVide(), unAutreArbre.estVide());

      EXPECT_TRUE(unAutreArbre.appartient(4));
      EXPECT_TRUE(unAutreArbre.appartient(5));
      EXPECT_TRUE(unAutreArbre.appartient(7));
      EXPECT_TRUE(unAutreArbre.appartient(8));
      EXPECT_TRUE(unAutreArbre.appartient(9));

      int parent;
      parent = unArbre.parent(7);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(9);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(8);
      EXPECT_EQ(5, parent);

      parent = unArbre.parent(4);
      EXPECT_EQ(5, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, OperateurEgalArbreVideOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      ArbreAVL<int, int> unAutreArbre = unArbre;

      EXPECT_EQ(unArbre.hauteur(), unAutreArbre.hauteur());
      EXPECT_EQ(unArbre.taille(), unAutreArbre.taille());
      EXPECT_EQ(unArbre.estVide(), unAutreArbre.estVide());

      EXPECT_TRUE(unAutreArbre.appartient(4));
      EXPECT_TRUE(unAutreArbre.appartient(5));
      EXPECT_TRUE(unAutreArbre.appartient(7));
      EXPECT_TRUE(unAutreArbre.appartient(8));
      EXPECT_TRUE(unAutreArbre.appartient(9));

      int parent;
      parent = unArbre.parent(7);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(9);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(8);
      EXPECT_EQ(5, parent);

      parent = unArbre.parent(4);
      EXPECT_EQ(5, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, OperateurEgalArbreNonVideOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      ArbreAVL<int, int> unAutreArbre;
      unAutreArbre.inserer(1,1);
      unAutreArbre.inserer(2,2);
      unAutreArbre.inserer(3,2);

      unAutreArbre = unArbre;

      EXPECT_EQ(unArbre.hauteur(), unAutreArbre.hauteur());
      EXPECT_EQ(unArbre.taille(), unAutreArbre.taille());
      EXPECT_EQ(unArbre.estVide(), unAutreArbre.estVide());

      EXPECT_TRUE(unAutreArbre.appartient(4));
      EXPECT_TRUE(unAutreArbre.appartient(5));
      EXPECT_TRUE(unAutreArbre.appartient(7));
      EXPECT_TRUE(unAutreArbre.appartient(8));
      EXPECT_TRUE(unAutreArbre.appartient(9));

      int parent;
      parent = unArbre.parent(7);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(9);
      EXPECT_EQ(8, parent);

      parent = unArbre.parent(8);
      EXPECT_EQ(5, parent);

      parent = unArbre.parent(4);
      EXPECT_EQ(5, parent);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, operateurEgalEgalArbresIdentiquesOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      ArbreAVL<int, int> unAutreArbre;
      unAutreArbre.inserer(5,5);
      unAutreArbre.inserer(4,4);
      unAutreArbre.inserer(7,7);
      unAutreArbre.inserer(9,9);
      unAutreArbre.inserer(8,8);

      EXPECT_TRUE(unArbre == unAutreArbre);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, operateurEgalEgalArbresDifferentsOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      ArbreAVL<int, int> unAutreArbre;
      unAutreArbre.inserer(5,5);
      unAutreArbre.inserer(9,9);
      unAutreArbre.inserer(8,8);

      EXPECT_FALSE(unArbre == unAutreArbre);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ListerOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      std::vector<std::pair<int, int > > liste = unArbre.lister();
      EXPECT_EQ(4, liste[0].first);
      EXPECT_EQ(5, liste[1].first);
      EXPECT_EQ(7, liste[2].first);
      EXPECT_EQ(8, liste[3].first);
      EXPECT_EQ(9, liste[4].first);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, ListerPreOrdreOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;
      unArbre.inserer(5,5);
      unArbre.inserer(4,4);
      unArbre.inserer(7,7);
      unArbre.inserer(9,9);
      unArbre.inserer(8,8);

      std::vector<std::pair<int, int > > liste = unArbre.listerPreOrdre();
      EXPECT_EQ(5, liste[0].first);
      EXPECT_EQ(4, liste[1].first);
      EXPECT_EQ(8, liste[2].first);
      EXPECT_EQ(7, liste[3].first);
      EXPECT_EQ(9, liste[4].first);
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

TEST(ArbreAVL, enleverUnElementArbreAvecUnElement)
{
   ArbreAVL<int, int> unArbre;

   unArbre.inserer(3,3);
   unArbre.enlever(3);

   EXPECT_EQ(0, unArbre.taille());
   EXPECT_TRUE(unArbre.estVide());
}

TEST(ArbreAVL, enleverArbreVideLanceException)
{
   ArbreAVL<int, int> unArbre;
   EXPECT_THROW(unArbre.enlever(2), logic_error);
}

TEST(ArbreAVL, enleverUnElementElementIncorrectLanceException)
{
   ArbreAVL<int, int> unArbre;

   unArbre.inserer(3,3);
   EXPECT_THROW(unArbre.enlever(2), logic_error);
}

TEST(ArbreAVL, enleverUneFeuille)
{
   ArbreAVL<int, int> unArbre;

   unArbre.inserer(3,3);
   unArbre.inserer(2,2);
   unArbre.inserer(4,4);

   unArbre.enlever(4);

   EXPECT_EQ(2, unArbre.taille());
   EXPECT_EQ(3, unArbre.parent(2));
}

TEST(ArbreAVL, enleverRacineAyantDeuxFils)
{
   ArbreAVL<int, int> unArbre;

   unArbre.inserer(3,3);
   unArbre.inserer(2,2);
   unArbre.inserer(4,4);

   unArbre.enlever(3);

   EXPECT_EQ(2, unArbre.taille());
   EXPECT_EQ(2, unArbre.compterNbNoeuds());
   EXPECT_EQ(1, unArbre.nbFeuilles());
   EXPECT_EQ(4, unArbre.parent(2));
   EXPECT_EQ(4, unArbre.successeur(2));
}

TEST(ArbreAVL, enleverTousLesElementsArbreAvec10ElementsOK)
{
   try
   {
      ArbreAVL<int, int> unArbre;

      unArbre.inserer(25,25);
      unArbre.inserer(12,12);
      unArbre.inserer(43,43);
      unArbre.inserer(8,8);
      unArbre.inserer(15,15);
      unArbre.inserer(38,38);
      unArbre.inserer(47,47);
      unArbre.inserer(4,4);
      unArbre.inserer(13,13);
      unArbre.inserer(18,18);

      EXPECT_EQ(unArbre.taille(), 10);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(25);
      EXPECT_EQ(unArbre.taille(), 9);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(12);
      EXPECT_EQ(unArbre.taille(), 8);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(43);
      EXPECT_EQ(unArbre.taille(), 7);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());
      EXPECT_EQ(unArbre.successeur(13), 15);

      unArbre.enlever(8);
      EXPECT_EQ(unArbre.taille(), 6);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(15);
      EXPECT_EQ(unArbre.taille(), 5);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(38);
      EXPECT_EQ(unArbre.taille(), 4);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(47);
      EXPECT_EQ(unArbre.taille(), 3);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(4);
      EXPECT_EQ(unArbre.taille(), 2);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(13);
      EXPECT_EQ(unArbre.taille(), 1);
      EXPECT_EQ(unArbre.lister().size(), unArbre.taille());

      unArbre.enlever(18);
      EXPECT_EQ(unArbre.taille(), 0);
      EXPECT_TRUE(unArbre.lister().empty());
      EXPECT_TRUE(unArbre.estVide());
   }
   catch (exception &e)
   {
      cerr << e.what();
      ADD_FAILURE();
   }
}

/**
 * \fn void imprime(T &x)
 * \brief Fonction qui imprime une donnée générique
 *
 * Cette fonction sert à tester les parcours de l'arbre
 */
template<typename T>
void imprime(T &x)
{
   cout << x << " ";
}

TEST(ArbreAVL, testerFonctionParcourAvecImprime)
{
   ArbreAVL<int, int> ab;
   ab.inserer(5,5);
   ab.inserer(3,3);
   ab.inserer(1,1);
   ab.inserer(7,7);
   ab.inserer(6,6);
   ab.inserer(2,2);
   ab.inserer(8,8);

   cout << "Taille de l'arbre: " << ab.taille() << endl;

   if (!ab.estVide())
      cout << "Arbre non vide" << endl;

   if (ab.appartient(3))
      cout << "3 fait partie de l'arbre" << endl;

   if (!ab.appartient(13))
      cout << "13 ne fait pas partie de l'arbre" << endl;

   ab.enlever(6);
   if (!ab.appartient(6))
      cout << "6 ne fait plus partie de l'arbre" << endl;

   cout << "La hauteur de l'arbre " << ab.hauteur() << endl;
   cout << "Le maximum dans l'arbre " << ab.max() << endl;
   cout << "Le minimum dans l'arbre " << ab.min() << endl;
   cout << "Le nombre de feuilles dans l'arbre " << ab.nbFeuilles() << endl;
   cout << "Le nombre de noeuds dans l'arbre " << ab.compterNbNoeuds() << endl;
   cout << "Le parent de 7 " << ab.parent(7) << endl;
   cout << "Le successeur de 7 " << ab.successeur(7) << endl;
   cout << "Le successeur de 2 " << ab.successeur(2) << endl;

   int tab[100];
   int nb = 0;
   ab.lister(tab, nb);
   cout << "Listage (tableau)\n";
   for (int i = 0; i < nb; i++)
      cout << tab[i] << " ";
   cout << "\n";

   std::vector<std::pair<int, int > > v = ab.lister();
   cout << "Listage (vector)\n";
   for (size_t i = 0; i < v.size(); i++)
      cout << v[i].first << "-" << v[i].second << " ";
   cout << "\n";

   cout << "Parcours en PreOrdre" << endl;
   ab.parcourirPreOrdre(imprime);
   cout << endl;
   cout << "Parcours en Ordre" << endl;
   ab.parcourirEnOrdre(imprime);
   cout << "\nParcours en PostOrdre" << endl;
   ab.parcourirPostOrdre(imprime);
   cout << "\nParcours par niveau" << endl;
   ab.parcourirParNiveau(imprime);
   cout << endl;

   ArbreAVL<int, int> ab2 = ab;
   cout << "\nParcours par PreOrdre du second arbre" << endl;
   ab2.parcourirPreOrdre(imprime);
   cout << endl;
}
